<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/72X72.ico">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/48X48.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/32X32.ico">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"issacyoung.cn","root":"/","scheme":"Pisces","version":"7.7.1","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
<meta property="og:type" content="website">
<meta property="og:title" content="Young‘s River">
<meta property="og:url" content="http://issacyoung.cn/page/2/index.html">
<meta property="og:site_name" content="Young‘s River">
<meta property="og:description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="Issac Young">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="http://issacyoung.cn/page/2/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome: true,
    isPost: false
  };
</script>

  <title>Young‘s River</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="Young‘s River" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <div>
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Young‘s River</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
        <p class="site-subtitle">一个正能量的程序员，喜欢码字，热爱运动，向往自由</p>
  </div>

  <div class="site-nav-right"></div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档</a>

  </li>
  </ul>

</nav>
</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

  <a href="https://github.com/IssacYoung2013" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content">
            

  <div class="posts-expand">
        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2021/11/07/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BPromethus/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2021/11/07/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BPromethus/" class="post-title-link" itemprop="url">一步一步之Promethus</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-11-07 10:45:04 / 修改时间：14:12:59" itemprop="dateCreated datePublished" datetime="2021-11-07T10:45:04+08:00">2021-11-07</time>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>197</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="Prometheus-介绍"><a href="#Prometheus-介绍" class="headerlink" title="Prometheus 介绍"></a>Prometheus 介绍</h2><blockquote>
<p>对于运行时的复杂系统，如果系统出了问题很难排查，不可能在运行时一边检查代码一边调试。需要在各种关键点加上监控，通过监控获取数据，指导我们进一步工作，解决问题。以一个车的系统而言，grafana就是仪表盘，prometheus就是一个时序数据库，存储数据库，提供查询，存储了系统在各个时间点的监控数据，而Grafana仪表盘上的数据就是通过查询Prometheus获取的。</p>
</blockquote>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2021/11/07/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BSkywalking%E6%90%AD%E5%BB%BA/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2021/11/07/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BSkywalking%E6%90%AD%E5%BB%BA/" class="post-title-link" itemprop="url">一步一步之Skywalking搭建</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-11-07 10:44:53" itemprop="dateCreated datePublished" datetime="2021-11-07T10:44:53+08:00">2021-11-07</time>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>0</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          
      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2021/11/07/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8Bjemter%E5%8E%8B%E6%B5%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2021/11/07/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8Bjemter%E5%8E%8B%E6%B5%8B/" class="post-title-link" itemprop="url">一步一步之jemter压测</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-11-07 10:44:30" itemprop="dateCreated datePublished" datetime="2021-11-07T10:44:30+08:00">2021-11-07</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-10-22 21:17:17" itemprop="dateModified" datetime="2023-10-22T21:17:17+08:00">2023-10-22</time>
              </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>0</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          
      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2021/11/07/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BSonar%E5%B9%B3%E5%8F%B0%E6%90%AD%E5%BB%BA/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2021/11/07/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BSonar%E5%B9%B3%E5%8F%B0%E6%90%AD%E5%BB%BA/" class="post-title-link" itemprop="url">一步一步之Sonar平台搭建</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-11-07 10:44:17 / 修改时间：11:17:27" itemprop="dateCreated datePublished" datetime="2021-11-07T10:44:17+08:00">2021-11-07</time>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>216</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="Sonar平台介绍"><a href="#Sonar平台介绍" class="headerlink" title="Sonar平台介绍"></a>Sonar平台介绍</h2><blockquote>
<p>Sonar 是代码检测的一个开源的质量管理平台，支持多种语言检测，可以从7个维度检测代码质量</p>
</blockquote>
<h2 id="Sonar能带来什么"><a href="#Sonar能带来什么" class="headerlink" title="Sonar能带来什么"></a>Sonar能带来什么</h2><ol>
<li><h4 id="糟糕的复杂度分布"><a href="#糟糕的复杂度分布" class="headerlink" title="糟糕的复杂度分布"></a>糟糕的复杂度分布</h4></li>
<li><h4 id="重复"><a href="#重复" class="headerlink" title="重复"></a>重复</h4></li>
<li><h4 id="缺乏单元测试"><a href="#缺乏单元测试" class="headerlink" title="缺乏单元测试"></a>缺乏单元测试</h4></li>
<li><h4 id="没有代码标准"><a href="#没有代码标准" class="headerlink" title="没有代码标准"></a>没有代码标准</h4></li>
<li><h4 id="没有足够或者过多的注释"><a href="#没有足够或者过多的注释" class="headerlink" title="没有足够或者过多的注释"></a>没有足够或者过多的注释</h4></li>
<li><h4 id="潜在的bug"><a href="#潜在的bug" class="headerlink" title="潜在的bug"></a>潜在的bug</h4></li>
<li><h4 id="糟糕的设计"><a href="#糟糕的设计" class="headerlink" title="糟糕的设计"></a>糟糕的设计</h4></li>
</ol>
<h2 id="搭建步骤"><a href="#搭建步骤" class="headerlink" title="搭建步骤"></a>搭建步骤</h2><h4 id="预置条件"><a href="#预置条件" class="headerlink" title="预置条件"></a>预置条件</h4><ol>
<li>已安装java</li>
<li>已安装MySQL数据库</li>
</ol>
<h4 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h4><ol>
<li>下载地址 <a href="https://www.sonarqube.org/success-download-community-edition/" target="_blank" rel="noopener">https://www.sonarqube.org/success-download-community-edition/</a> 下载的社区免费版</li>
<li>下载中文补丁包 </li>
</ol>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2021/09/15/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BSpock/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2021/09/15/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BSpock/" class="post-title-link" itemprop="url">一步一步之Spock</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-09-15 15:24:57" itemprop="dateCreated datePublished" datetime="2021-09-15T15:24:57+08:00">2021-09-15</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-10-13 16:33:04" itemprop="dateModified" datetime="2021-10-13T16:33:04+08:00">2021-10-13</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Java/" itemprop="url" rel="index">
                    <span itemprop="name">Java</span>
                  </a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>5.8k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <blockquote>
<p>为什么测试？</p>
<ol>
<li>整理编码思路</li>
<li>增加对项目的理解</li>
</ol>
<p>为什么做单元测试？</p>
<ol>
<li>省时省力，及早发现bug</li>
<li>方便重构</li>
</ol>
<p>为什么不做单元测试？</p>
<ol>
<li>难以理解、维护，业务代码的单测代码量可能比业务代码本身还多</li>
<li>依赖难以去除，数据库、微服务依赖</li>
</ol>
</blockquote>
<h2 id="Spock简介"><a href="#Spock简介" class="headerlink" title="Spock简介"></a>Spock简介</h2><p>Spock国外一款优秀的测试框架，基于BDD（行为驱动开发）思想，结合Groovy动态语言，简洁、高效、层次清晰，IDE兼容好，自带Mock功能。相比JUnit、Mockito，使用起来更简单。</p>
<h4 id="Groovy"><a href="#Groovy" class="headerlink" title="Groovy"></a>Groovy</h4><ul>
<li>扩展java为目的的语言</li>
<li>语法精简、表达性强</li>
<li>典型应用：jenkins、elasticsearch、gradle</li>
</ul>
<h3 id="为什么是Spock"><a href="#为什么是Spock" class="headerlink" title="为什么是Spock"></a>为什么是Spock</h3><h4 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h4><ul>
<li>遵循BDD模式、功能强大、语义规范、可读性强、易于维护</li>
<li>描述测试步骤用自然语言描述 give 、when、then、expect</li>
<li>兼容mock</li>
<li>习惯上单元测试，提升代码质量的利器</li>
</ul>
<h4 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h4><ul>
<li>groovy 的学习成本</li>
<li>不支持静态方法mock，需要引入PowerMockito</li>
</ul>
<h3 id="Spock中的概念"><a href="#Spock中的概念" class="headerlink" title="Spock中的概念"></a>Spock中的概念</h3><h4 id="Specification"><a href="#Specification" class="headerlink" title="Specification"></a>Specification</h4><p>字面意思是规范、规格，测试类需要继承Specification类</p>
<h4 id="Fields"><a href="#Fields" class="headerlink" title="Fields"></a>Fields</h4><p>Specification类中可以定义字段，会在每个测试方法前重新初始化</p>
<h4 id="Fixed-Methods"><a href="#Fixed-Methods" class="headerlink" title="Fixed Methods"></a>Fixed Methods</h4><p>固定函数，类似junit中的</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> setup() &#123;&#125; <span class="comment">// 每个测试方法前执行</span></span><br><span class="line"><span class="keyword">def</span> cleanup() &#123;&#125; <span class="comment">// 每个测试方法后执行</span></span><br><span class="line"><span class="keyword">def</span> setupSpec() &#123;&#125; <span class="comment">// 第一个测试方法前执行</span></span><br><span class="line"><span class="keyword">def</span> cleanupSpec() &#123;&#125; <span class="comment">// 最后一个测试方法后执行</span></span><br></pre></td></tr></table></figure>

<h4 id="Blocks"><a href="#Blocks" class="headerlink" title="Blocks"></a>Blocks</h4><p>每个测试方法划分为不同的block，不同的block表示测试处于不同的阶段</p>
<ul>
<li>setup / given 测试函数初始化</li>
<li>when / then 需要搭配使用，when 中执行待测试函数，then 中判断是否符合预期</li>
<li>expect 精简版的 when / then</li>
<li>thrown 验证异常</li>
<li>where 测试数据</li>
</ul>
<h2 id="Spock使用"><a href="#Spock使用" class="headerlink" title="Spock使用"></a>Spock使用</h2><h3 id="添加依赖"><a href="#添加依赖" class="headerlink" title="添加依赖"></a>添加依赖</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--引入spock 核心包--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.spockframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spock-core<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.3-groovy-2.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--引入spock 与 spring 集成包--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.spockframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spock-spring<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.3-groovy-2.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--引入 groovy 依赖--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.codehaus.groovy<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>groovy-all<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.5.7<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="基础语法"><a href="#基础语法" class="headerlink" title="基础语法"></a>基础语法</h3><blockquote>
<p>对于springboot项目，groovy测试类的文件必须创建在 test/groovy 下，而不是 test/java，文件类型是 Groovy文件</p>
</blockquote>
<ul>
<li>given 定义前置条件</li>
<li>and 其他前置条件</li>
<li>when 当发生一个特定事件</li>
<li>then 产生的后置结果</li>
<li>expect 随处可用的断言</li>
<li>with 判断对象</li>
<li>where 测试数据</li>
<li>setup 单个测试方法前置</li>
<li>setupSpec 整个测试环境前置</li>
<li>cleanup 单个测试方法后置</li>
<li>cleanupSpec 整个测试环境后置</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Title</span>(<span class="string">"标题：计算"</span>)</span><br><span class="line"><span class="meta">@Narrative</span>(<span class="string">"Spock单测示例"</span>)</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CalculatorTest</span> <span class="keyword">extends</span> <span class="title">Specification</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function">def <span class="title">setup</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        println <span class="string">"=====方法测试前置===="</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function">def <span class="title">cleanup</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        println <span class="string">"=====方法测试后置===="</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function">def <span class="title">setupSpec</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        println <span class="string">"=====整个测试环境前置===="</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function">def <span class="title">cleanupSpec</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        println <span class="string">"=====整个测试环境后置===="</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    def <span class="string">"test add"</span>() &#123;</span><br><span class="line">        expect:</span><br><span class="line">        Calculator.add(<span class="number">1</span>, <span class="number">1</span>) == <span class="number">2</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    def <span class="string">"test and given"</span>() &#123;</span><br><span class="line">        given:</span><br><span class="line">        def num1 = <span class="number">1</span></span><br><span class="line">        def num2 = <span class="number">1</span></span><br><span class="line"></span><br><span class="line">        and:</span><br><span class="line">        def result = <span class="number">2</span></span><br><span class="line"></span><br><span class="line">        expect:</span><br><span class="line">        Calculator.add(num1, num2) == result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 表示where下面的每一行作为一个单独的测试用例</span></span><br><span class="line">    <span class="meta">@Unroll</span></span><br><span class="line">    def <span class="string">"test add with expect where"</span>() &#123;</span><br><span class="line">        expect:</span><br><span class="line">        Calculator.add(num1, num2) == result</span><br><span class="line"></span><br><span class="line">        where:</span><br><span class="line">        num1 | num2 | result</span><br><span class="line">        <span class="number">1</span>    | <span class="number">1</span>    | <span class="number">2</span></span><br><span class="line">        <span class="number">1</span>    | <span class="number">2</span>    | <span class="number">3</span></span><br><span class="line">        <span class="number">1</span>    | <span class="number">3</span>    | <span class="number">4</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// #num1动态替换成字面量</span></span><br><span class="line">    <span class="meta">@Unroll</span></span><br><span class="line">    def <span class="string">"test add with expect where unroll arr by #num1 + #num2 = #result"</span>() &#123;</span><br><span class="line">        expect:</span><br><span class="line">        Calculator.add(num1, num2) == result</span><br><span class="line"></span><br><span class="line">        where:</span><br><span class="line">        num1 &lt;&lt; [<span class="number">1</span>, <span class="number">1</span>, <span class="number">2</span>]</span><br><span class="line">        num2 &lt;&lt; [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line">        result &lt;&lt; [<span class="number">2</span>, <span class="number">3</span>, <span class="number">5</span>]</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Unroll</span></span><br><span class="line">    def <span class="string">"test int dived zero exception"</span>() &#123;</span><br><span class="line">        when:</span><br><span class="line">        Calculator.divideInt(<span class="number">1</span>, <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        then:</span><br><span class="line">        def ex = thrown(ArithmeticException)</span><br><span class="line">        ex.message == <span class="string">"/ by zero"</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Timeout</span>(value = <span class="number">900</span>, unit = TimeUnit.MILLISECONDS)</span><br><span class="line">    def <span class="string">"test timeout"</span>() &#123;</span><br><span class="line">        expect:</span><br><span class="line">        Thread.sleep(<span class="number">500</span>)</span><br><span class="line">        <span class="number">1</span> == <span class="number">1</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Ignore</span>(<span class="string">"忽略这个测试方法"</span>)</span><br><span class="line">    def <span class="string">"测试方法1"</span>() &#123;</span><br><span class="line">        given: <span class="string">"给定一个前置条件"</span></span><br><span class="line">        <span class="comment">//<span class="doctag">TODO:</span> code here</span></span><br><span class="line">        and: <span class="string">"其他前置条件"</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        expect: <span class="string">"随处可用的断言"</span></span><br><span class="line">        <span class="comment">//<span class="doctag">TODO:</span> code here</span></span><br><span class="line">        when: <span class="string">"当发生一个特定的事件"</span></span><br><span class="line">        <span class="comment">//<span class="doctag">TODO:</span> code here</span></span><br><span class="line">        and: <span class="string">"其他的触发条件"</span></span><br><span class="line"></span><br><span class="line">        then: <span class="string">"产生的后置结果"</span></span><br><span class="line">        <span class="comment">//<span class="doctag">TODO:</span> code here</span></span><br><span class="line">        and: <span class="string">"同时产生的其他结果"</span></span><br><span class="line"></span><br><span class="line">        where: <span class="string">"不是必需的测试数据"</span></span><br><span class="line">        input1 | input2 || output</span><br><span class="line">        <span class="number">111</span>    | <span class="number">222</span>    || <span class="number">333</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@IgnoreRest</span></span><br><span class="line">    <span class="comment">//只测试这个方法，而忽略所有其他方法</span></span><br><span class="line">    def <span class="string">"测试方法2"</span>() &#123;</span><br><span class="line">        <span class="comment">//<span class="doctag">TODO:</span> code here</span></span><br><span class="line">        expect:</span><br><span class="line">        <span class="number">1</span> == <span class="number">1</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Mock"><a href="#Mock" class="headerlink" title="Mock"></a>Mock</h3><p>mock的好处在于，单个类依赖的下游类可以mock，方便单元测试，也会有各式的问题。</p>
<h4 id="动态mock"><a href="#动态mock" class="headerlink" title="动态mock"></a>动态mock</h4><p>对于平常的业务开发，分层一般是 Serivce、DAO层，如果单测Service的代码，DAO的方法就可以mock，不必依赖数据库就可以单测。下面以用户登录为例，</p>
<p><code>UserDAO.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserDao</span> </span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 模拟数据库</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> Map&lt;String, User&gt; userMap = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        userMap.put(<span class="string">"k"</span>, <span class="keyword">new</span> User(<span class="string">"k"</span>, <span class="number">1</span>, <span class="string">"123"</span>));</span><br><span class="line">        userMap.put(<span class="string">"i"</span>, <span class="keyword">new</span> User(<span class="string">"i"</span>, <span class="number">2</span>, <span class="string">"456"</span>));</span><br><span class="line">        userMap.put(<span class="string">"w"</span>, <span class="keyword">new</span> User(<span class="string">"w"</span>, <span class="number">3</span>, <span class="string">"789"</span>));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 通过用户名查询用户</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> name</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> User <span class="title">findByName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> userMap.get(name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>UserService.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserService</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> UserDao userDao;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> User <span class="title">findByName</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> userDao.findByName(name);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">loginAfter</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"登录成功"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">login</span><span class="params">(String name, String passwd)</span> </span>&#123;</span><br><span class="line">        User user = findByName(name);</span><br><span class="line">        <span class="keyword">if</span> (user == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(name + <span class="string">"不存在"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (!user.getPasswd().equals(passwd)) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(name + <span class="string">"密码输入错误"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        loginAfter();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>UserSericeUnitTest.groovy</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UserServiceUnitTest</span> <span class="keyword">extends</span> <span class="title">Specification</span> </span>&#123;</span><br><span class="line">    UserService userService = <span class="keyword">new</span> UserService()</span><br><span class="line">    UserDao userDao = Mock(UserDao)</span><br><span class="line"></span><br><span class="line">    <span class="function">def <span class="title">setup</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        userService.userDao = userDao;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    def <span class="string">"test login with success"</span>() &#123;</span><br><span class="line">        when:</span><br><span class="line">        userService.login(<span class="string">"k"</span>, <span class="string">"p"</span>)</span><br><span class="line"></span><br><span class="line">        then:</span><br><span class="line">        <span class="number">1</span> * userDao.findByName(<span class="string">"k"</span>) &gt;&gt; <span class="keyword">new</span> User(<span class="string">"k"</span>, <span class="number">12</span>, <span class="string">"p"</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    def <span class="string">"test login with error"</span>() &#123;</span><br><span class="line">        given:</span><br><span class="line">        def name = <span class="string">"k"</span></span><br><span class="line">        def passwd = <span class="string">"p"</span></span><br><span class="line"></span><br><span class="line">        when:</span><br><span class="line">        userService.login(name, passwd)</span><br><span class="line"></span><br><span class="line">        then:</span><br><span class="line">        <span class="number">1</span> * userDao.findByName(name) &gt;&gt; <span class="keyword">null</span></span><br><span class="line"></span><br><span class="line">        then:</span><br><span class="line">        def e = thrown(RuntimeException)</span><br><span class="line">        e.message == <span class="string">"$&#123;name&#125;不存在"</span></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Unroll</span></span><br><span class="line">    def <span class="string">"test login with "</span>() &#123;</span><br><span class="line">        when:</span><br><span class="line">        userService.login(name, passwd)</span><br><span class="line"></span><br><span class="line">        then:</span><br><span class="line">        userDao.findByName(<span class="string">"k"</span>) &gt;&gt; <span class="keyword">null</span></span><br><span class="line">        userDao.findByName(<span class="string">"k1"</span>) &gt;&gt; <span class="keyword">new</span> User(<span class="string">"k1"</span>, <span class="number">12</span>, <span class="string">"p"</span>)</span><br><span class="line"></span><br><span class="line">        then:</span><br><span class="line">        def e = thrown(RuntimeException)</span><br><span class="line">        e.message == errMsg</span><br><span class="line"></span><br><span class="line">        where:</span><br><span class="line">        name | passwd | errMsg</span><br><span class="line">        <span class="string">"k"</span>  | <span class="string">"k"</span>    | <span class="string">"$&#123;name&#125;不存在"</span></span><br><span class="line">        <span class="string">"k1"</span> | <span class="string">"p1"</span>   | <span class="string">"$&#123;name&#125;密码输入错误"</span></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    def <span class="string">"test findByName by verity"</span>() &#123;</span><br><span class="line">        given:</span><br><span class="line">        def userDao = Mock(UserDao)</span><br><span class="line"></span><br><span class="line">        when:</span><br><span class="line">        userDao.findByName(<span class="string">"kk"</span>) &gt;&gt; <span class="keyword">new</span> User(<span class="string">"kk"</span>, <span class="number">12</span>, <span class="string">"33"</span>)</span><br><span class="line"></span><br><span class="line">        then:</span><br><span class="line">        def user = userDao.findByName(<span class="string">"kk"</span>)</span><br><span class="line">        with(user) &#123;</span><br><span class="line">            name == <span class="string">"kk"</span></span><br><span class="line">            age == <span class="number">12</span></span><br><span class="line">            passwd == <span class="string">"33"</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="抽象类、静态类方法mock"><a href="#抽象类、静态类方法mock" class="headerlink" title="抽象类、静态类方法mock"></a>抽象类、静态类方法mock</h4><p>借用PowerMockito</p>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2021/07/17/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8B%E7%BA%BF%E7%A8%8B%E6%B1%A0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2021/07/17/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8B%E7%BA%BF%E7%A8%8B%E6%B1%A0/" class="post-title-link" itemprop="url">一步一步之线程池</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-07-17 11:19:10" itemprop="dateCreated datePublished" datetime="2021-07-17T11:19:10+08:00">2021-07-17</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-07-20 14:26:21" itemprop="dateModified" datetime="2021-07-20T14:26:21+08:00">2021-07-20</time>
              </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>1.9k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="线程池"><a href="#线程池" class="headerlink" title="线程池"></a>线程池</h2><p>特殊的线程池，commons-pool2 实现线程池</p>
<h3 id="好处"><a href="#好处" class="headerlink" title="好处"></a>好处</h3><ul>
<li>重用已存在的线程</li>
<li>并发控制</li>
<li>功能强大，定时执行、单线程执行</li>
</ul>
<h3 id="线程池参数"><a href="#线程池参数" class="headerlink" title="线程池参数"></a>线程池参数</h3><ul>
<li>corePoolSize 核心线程数</li>
<li>maximumPoolSize 最大线程数</li>
<li>keepAliveTime 允许空闲时间，默认情况下指的是非核心线程的空闲时间，核心线程即使空闲不会被回收，alloow</li>
<li>TimeUnit 时间单位</li>
<li>workQueue 存储等待执行的任务，BlockQueue</li>
<li>threadFactory 创建线程相同的优先级，非守护线程、有线程名称；privilegedThreadFactory</li>
<li>rejectHandler 拒绝任务的策略，workQueue 满了且无空闲线程<ul>
<li>AbortPolicy 抛异常</li>
<li>CallerRusPolicy 用调用者所在的线程执行任务</li>
<li>DiscardOldestPolicy 丢弃队列中最靠前的任务</li>
<li>DiscardPolicy 直接丢弃</li>
</ul>
</li>
</ul>
<p>类比：</p>
<p>公司正常，正式员工（核心线程）处理任务，任务处理不过来，临时工（非核心线程）处理任务，预先设定公司的招聘人数（正式员工的数量），maximumPoolSize（正式员工、临时工），keepAliveTime 指员工空闲时间超过一定的时间就会解雇（默认饰解聘临时工，allowCoreThreadTimeout=true，也会解聘正式员工），workQueue 任务规划，threadFactory 人才市场，rejectHandler 怎么丢弃任务。</p>
<h3 id="核心api"><a href="#核心api" class="headerlink" title="核心api"></a>核心api</h3><ul>
<li>execute 提交任务，交给线程池执行</li>
<li>submit 提交任务，能够返回执行结果</li>
<li>shutdown 关闭线程池，等任务都执行完毕</li>
<li>shutdownNow 直接关闭线程池</li>
</ul>
<h3 id="核心api-监控"><a href="#核心api-监控" class="headerlink" title="核心api 监控"></a>核心api 监控</h3><ul>
<li>getTaskCount() 返回线程池已执行和未执行的任务总数</li>
<li>getCompletedTaskCount 已完成的任务数量</li>
<li>getPoolSize 线程池当前的线程数量</li>
<li>getActiveAcount 线程池正在执行任务的线程数量</li>
</ul>
<h3 id="线程池状态"><a href="#线程池状态" class="headerlink" title="线程池状态"></a>线程池状态</h3><ul>
<li>RUNNING 接收任务</li>
<li>SHUTDOWN 不能提交新任务，可以处理阻塞任务</li>
<li>STOP 不能提交新任务，不可以处理阻塞任务</li>
<li>TIDYING 所有任务终止，工作线程数量为空</li>
<li>TERMINATED 线程池彻底终止</li>
</ul>
<h3 id="BlockingQueue详解和调优"><a href="#BlockingQueue详解和调优" class="headerlink" title="BlockingQueue详解和调优"></a>BlockingQueue详解和调优</h3><h4 id="是什么"><a href="#是什么" class="headerlink" title="是什么"></a>是什么</h4><ul>
<li>阻塞队列，排队，先进先出；</li>
<li>当队列为空，获取对象会阻塞；当队列慢，添加对象会阻塞</li>
</ul>
<h4 id="作用"><a href="#作用" class="headerlink" title="作用"></a>作用</h4><ul>
<li>实现队列应具备的功能</li>
<li>多线程环境下自动管理线程的等待与唤醒</li>
</ul>
<h4 id="api"><a href="#api" class="headerlink" title="api"></a>api</h4><ul>
<li><p>抛出异常、阻塞、超时</p>
</li>
<li><p>插入 add offer put </p>
</li>
<li><p>移除 remove poll take</p>
</li>
<li><p>检查 element peek</p>
</li>
</ul>
<h4 id="常用实现"><a href="#常用实现" class="headerlink" title="常用实现"></a>常用实现</h4><table>
<thead>
<tr>
<th>类名</th>
<th>有界</th>
<th>特性</th>
</tr>
</thead>
<tbody><tr>
<td>ArrayBlockingQueue</td>
<td>有</td>
<td>1. 内部基于数组实现<br>2. 初始化必须指定容量大小<br>3. 一旦容量大小指定就不能修改</td>
</tr>
<tr>
<td>LinkedTransferQueue</td>
<td>无</td>
<td>1. 底层基于链表<br>2. 用于数据交换<br>3. 比其他队列多了transfer()以及tryTransfer() 方法</td>
</tr>
<tr>
<td>DelayQueue</td>
<td>无</td>
<td></td>
</tr>
<tr>
<td>LinkedBlockedQueue</td>
<td>有/无</td>
<td>1. 容量可选，默认Integer.MAX_VALUEM<br>2. 内部基于链表</td>
</tr>
<tr>
<td>PriorityBlockingQueue</td>
<td>无</td>
<td>1. 带优先级的阻塞队列<br>2. 允许插入NULL对象<br>3. 元素必须实现Comparable接口，队列的排序规则需要用</td>
</tr>
<tr>
<td>SynchronousQueue</td>
<td>有</td>
<td>1. 不存储元素，内部容量为0</td>
</tr>
</tbody></table>
<p>无界队列，任务可以无限排队；</p>
<h4 id="调优技巧"><a href="#调优技巧" class="headerlink" title="调优技巧"></a>调优技巧</h4><ul>
<li>合理设置corePoolSize、maximumPoolSize、workQueue容量</li>
</ul>
<h4 id="ScheduledThreadPoolExecutor"><a href="#ScheduledThreadPoolExecutor" class="headerlink" title="ScheduledThreadPoolExecutor"></a>ScheduledThreadPoolExecutor</h4><ul>
<li>延迟任务、周期性任务</li>
</ul>
<h3 id="线程池调优"><a href="#线程池调优" class="headerlink" title="线程池调优"></a>线程池调优</h3><ul>
<li>线程数调优</li>
<li>BlockQueue调优</li>
</ul>
<h4 id="线程数调优"><a href="#线程数调优" class="headerlink" title="线程数调优"></a>线程数调优</h4><p>线程数多，线程之间竞争激烈；太少，浪费资源；环境在变化，不同时间会有差异，计算出相对合理的数量</p>
<h4 id="任务类型"><a href="#任务类型" class="headerlink" title="任务类型"></a>任务类型</h4><ul>
<li>CPU密集型任务，大型复杂计算任务，挖矿（计算、排序）</li>
<li>IO密集型任务，操作数据库任务，增删改查的任务</li>
<li>混合型任务，CPU和IO都需要</li>
</ul>
<h4 id="CPU密集任务"><a href="#CPU密集任务" class="headerlink" title="CPU密集任务"></a>CPU密集任务</h4><ul>
<li>经验公式：N（CPU核心数）+1，为什么，设置为CPU核数没有竞争没有浪费，如果有一个线程暂停、中断，踢足球候补队员</li>
</ul>
<h4 id="IO密集型任务"><a href="#IO密集型任务" class="headerlink" title="IO密集型任务"></a>IO密集型任务</h4><ul>
<li>经验公式：2N，多配置线程</li>
</ul>
<h4 id="估算经验公式"><a href="#估算经验公式" class="headerlink" title="估算经验公式"></a>估算经验公式</h4><ul>
<li>N * U * (1+WT/ST)<ul>
<li>N CPU核心数</li>
<li>U 目标CPU利用率</li>
<li>WT 线程等待时间</li>
<li>ST 线程运行时间</li>
</ul>
</li>
</ul>
<p><strong>jvisualvm -&gt;profiler-&gt;cpu 性能分析，总时间-自用时间(WT)，自用时间（ST）</strong></p>
<h4 id="BlockingQueue调优"><a href="#BlockingQueue调优" class="headerlink" title="BlockingQueue调优"></a>BlockingQueue调优</h4><ul>
<li>单个任务占用内存</li>
<li>线程池计划占用内存</li>
</ul>
<h4 id="业务评估"><a href="#业务评估" class="headerlink" title="业务评估"></a>业务评估</h4><p>多次压测，逐步调整（+1+2、-2-1）</p>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2021/07/08/java%E5%B8%B8%E7%94%A8%E9%9D%A2%E8%AF%95%E9%A2%98/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2021/07/08/java%E5%B8%B8%E7%94%A8%E9%9D%A2%E8%AF%95%E9%A2%98/" class="post-title-link" itemprop="url">java常用面试题</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-07-08 18:15:16" itemprop="dateCreated datePublished" datetime="2021-07-08T18:15:16+08:00">2021-07-08</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-07-20 16:29:22" itemprop="dateModified" datetime="2021-07-20T16:29:22+08:00">2021-07-20</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/interview/" itemprop="url" rel="index">
                    <span itemprop="name">interview</span>
                  </a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>2k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="基础题目"><a href="#基础题目" class="headerlink" title="基础题目"></a>基础题目</h2><h3 id="JVM"><a href="#JVM" class="headerlink" title="JVM"></a>JVM</h3><ol>
<li><p>介绍下JVM内存区域</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; </span><br><span class="line">线程私有区域【程序计数器、虚拟机栈、本地方法区】、线程共享区【Java堆、方法区】、直接内存</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 知道5个区域，</span><br></pre></td></tr></table></figure>
</li>
<li><p>介绍下jvm GC，如何确定垃圾？介绍几种垃圾回收算法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; </span><br><span class="line">引用计数法、可达性分析【根节点，ApplicationContext】</span><br><span class="line">新生代、老年代</span><br><span class="line">标记清除算法【碎片化严重】、复制算法【效率低】、标记整理算法【存活对象移到内存一端】、分代收集算法</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 确定；堆</span><br></pre></td></tr></table></figure>
</li>
<li><p>介绍下 io 、nio</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;</span><br><span class="line">nio 多路复用io，有一个线程不断轮询多个socket状态，socket有读写事件，才执行实际io操作，通过一个线程管理多个 socket。三大核心，channel、buffer、selector，传统io基于字节流和字符流操作，nio基于buffer和channel操作，数据总是从通道读取到缓存区或者从缓冲区写入到通道中，selector 用于坚挺多个通道的事件。io是阻塞的，当一个线程read()或者write()，线程阻塞，直到有一些数据被读取或者写入。</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 不知道</span><br></pre></td></tr></table></figure>
</li>
<li><p>类加载机制</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;</span><br><span class="line">类加载分5个部分，加载【内存中生成一个代表这个类的java.lang.Class对象，不一定是class文件，zip读取或者运行时计算】、验证、准备【为类分配内存并设置类变量的初始值】、解析【符号引用（clasa文件类型）替换为直接引用】、初始化【启动类加载期】。</span><br><span class="line">双亲委派</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;</span><br></pre></td></tr></table></figure>

</li>
</ol>
<h3 id="Java集合"><a href="#Java集合" class="headerlink" title="Java集合"></a>Java集合</h3><ol>
<li><p>ArrayList 、LinkedList</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;</span><br><span class="line">ArrayList 数组实现，允许快速随机访问，数组大小不能满足增加存储能力，将已经有的数据复制到新的存储空间，插入或者删除元素代价高；</span><br><span class="line">LinkedList 链表结构存储，适合动态插入或者删除，随机访问和便利速度较慢</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 知道</span><br></pre></td></tr></table></figure>
</li>
<li><p>HashMap</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">数组+链表+红黑树，允许key为null，非线程安全，hashMap里是一个数组，数组每个元素是个单向链表，每个元素是Entry实例，key、value、hash值，next;</span><br><span class="line">java8 利用了红黑树。</span><br><span class="line">1. 每个节点或黑或红</span><br><span class="line">2. 根节点是黑</span><br><span class="line">3. 叶子节点是黑</span><br><span class="line">4. 如果一个节点是红色，子节点必须是黑色</span><br><span class="line">5. 从一个节点到该节点的子孙节点所有路径包含相同数目的黑节点</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 能说出过程</span><br></pre></td></tr></table></figure>



</li>
</ol>
<h3 id="Java多线程并发"><a href="#Java多线程并发" class="headerlink" title="Java多线程并发"></a>Java多线程并发</h3><ol>
<li><p>synchronized 和 ReentrantLock</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;</span><br><span class="line">ReentrantLock 通过lock()、unlock()操作，可中断，公平锁。</span><br><span class="line">Synchronized 任意非null对象作为锁，关键字。</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">重量级锁</span><br><span class="line">&#x2F;&#x2F; 不知道lock</span><br></pre></td></tr></table></figure>



</li>
</ol>
<ol start="2">
<li><p>线程池</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;</span><br><span class="line">控制运行的线程数量，处理过程中将任务放入队列，然后在线程创建后启动任务。如果线程数量超过最大数量的线程排队等候，等其他线程执行完毕，再从队列中取出任务执行。线程复用、控制并发、管理线程。</span><br><span class="line">1. 线程管理器</span><br><span class="line">2. 工作线程</span><br><span class="line">3. 任务接口</span><br><span class="line">4. 任务队列</span><br><span class="line">构造参数</span><br><span class="line">1. corePoolSize 线程数量</span><br><span class="line">2. maximumPoolSize 最大线程数量</span><br><span class="line">3. keepAliveTime 超过corePoolSize 多余的空闲线程存活时间</span><br><span class="line">4. unit 单位</span><br><span class="line">5. workQueue 任务对象</span><br><span class="line">6. threadFactory 线程工程</span><br><span class="line">7. handler 拒绝策略</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">没有使用过；</span><br><span class="line">知道原理；</span><br></pre></td></tr></table></figure>

</li>
</ol>
<h3 id="Java基础"><a href="#Java基础" class="headerlink" title="Java基础"></a>Java基础</h3><h2 id="技术深度"><a href="#技术深度" class="headerlink" title="技术深度"></a>技术深度</h2><ol>
<li><p>一致性hash算法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">分布式算法，用于负载均衡</span><br><span class="line">1. 建立环形空间</span><br><span class="line">	将value映射到32位的key值</span><br><span class="line">2. 需要缓存的内容映射到hash空间</span><br><span class="line">    4个对象通过hash函数计算出hash值key在环上分布</span><br><span class="line">3. 服务节点映射到hash空间</span><br><span class="line">4. 对象映射到服务节点</span><br><span class="line">虚拟节点引入，保持平衡</span><br></pre></td></tr></table></figure>
</li>
<li><p>数据库索引</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;</span><br><span class="line">平衡多路搜索树，B树。每个节点至多有m个孩子，至少有ceil(m&#x2F;2)个孩子，所有叶子节点出现同一层</span><br><span class="line">1. 选择唯一值</span><br><span class="line">2. 排序、分组和联合操作的字段建立索引</span><br><span class="line">3. 经常查询的字段建立索引</span><br><span class="line">5. 使用数据量少的索引</span><br><span class="line">6. 最左匹配原则</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">知道；</span><br></pre></td></tr></table></figure>



</li>
</ol>
<ol start="3">
<li><p>redis</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">pipeline 和 m操作的区别？</span><br><span class="line">1. 原子和非原子</span><br><span class="line">2. pipeline 作用在一个节点</span><br><span class="line">单线程为什么这么快？</span><br><span class="line">1. 纯内存</span><br><span class="line">2. 非阻塞IO epoll 模型</span><br><span class="line">3. 避免线程切换和竞态消耗</span><br><span class="line">平常如何使用redis</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">知道；</span><br></pre></td></tr></table></figure>



</li>
</ol>
<h2 id="技术框架"><a href="#技术框架" class="headerlink" title="技术框架"></a>技术框架</h2><ol>
<li><p>看过哪些开源框架的源码</p>
<p>springboot ，围绕启动事件说明启动流程，如何做到自动装配。</p>
</li>
</ol>
<h2 id="系统架构"><a href="#系统架构" class="headerlink" title="系统架构"></a>系统架构</h2><h2 id="分布式系统"><a href="#分布式系统" class="headerlink" title="分布式系统"></a>分布式系统</h2><h2 id="实战能力"><a href="#实战能力" class="headerlink" title="实战能力"></a>实战能力</h2><h2 id="软能力"><a href="#软能力" class="headerlink" title="软能力"></a>软能力</h2>
      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2021/05/13/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BSpringCloudAlibaba/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2021/05/13/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BSpringCloudAlibaba/" class="post-title-link" itemprop="url">一步一步之SpringCloudAlibaba</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-05-13 07:52:23" itemprop="dateCreated datePublished" datetime="2021-05-13T07:52:23+08:00">2021-05-13</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-07-07 20:22:28" itemprop="dateModified" datetime="2021-07-07T20:22:28+08:00">2021-07-07</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E5%BE%AE%E6%9C%8D%E5%8A%A1/" itemprop="url" rel="index">
                    <span itemprop="name">微服务</span>
                  </a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>817</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="微服务发展史"><a href="#微服务发展史" class="headerlink" title="微服务发展史"></a>微服务发展史</h2><h3 id="单体架构到分布式架构的演进"><a href="#单体架构到分布式架构的演进" class="headerlink" title="单体架构到分布式架构的演进"></a>单体架构到分布式架构的演进</h3><p>架构的发展可能都会经历单体架构、垂直化和集群、SOA（面向服务架构）、微服务架构。通常来说，如果一个war或者jar包包含一个应用的所有功能，我们称之为单体架构。</p>
<p>用户流量变大后，1）横向增加服务器</p>
<h2 id="基于Sentinel的微服务限流及熔断"><a href="#基于Sentinel的微服务限流及熔断" class="headerlink" title="基于Sentinel的微服务限流及熔断"></a>基于Sentinel的微服务限流及熔断</h2><p>高并发场景中，访问量会远超系统所能处理的最大处理并发数。常见的系统保护策略包括，限流、降级、熔断等。</p>
<h2 id="分布式事务"><a href="#分布式事务" class="headerlink" title="分布式事务"></a>分布式事务</h2><p>分布式数据一致性，如何在分布式场景保证多个节点数据的一致性。核心原因，多数据库、多源数据库（MYSQL和REDIS）。</p>
<h3 id="分布式理论模型"><a href="#分布式理论模型" class="headerlink" title="分布式理论模型"></a>分布式理论模型</h3><h4 id="分布式事务模型"><a href="#分布式事务模型" class="headerlink" title="分布式事务模型"></a>分布式事务模型</h4><ul>
<li><p>AP 应用，从TM管理的RM获取连接，发起全局事务，生成全局事务id</p>
</li>
<li><p>RM 资源管理器</p>
</li>
<li><p>TM 事务管理器，管理多个RM</p>
</li>
</ul>
<h4 id="CAP定理"><a href="#CAP定理" class="headerlink" title="CAP定理"></a>CAP定理</h4><p>分布式系统不能同时满足一致性（Consistency）、可用性（Availablity）、分区容错性（Partition Tolerance）这三个基本要求，最多满足其中两个。</p>
<ul>
<li>C：数据在多个副本中保持强一致</li>
<li>A：系统对外提供的服务必须一直处于可用状态</li>
<li>P：在分布式系统中遇到网络分区故障（脑裂），系统仍然能够正常对外提供服务</li>
</ul>
<h4 id="BASE-理论"><a href="#BASE-理论" class="headerlink" title="BASE 理论"></a>BASE 理论</h4><p>牺牲数据强一致性获得高可用</p>
<ul>
<li>Basically Availiable 基本可用，允许损失一部分功能的可用性</li>
<li>Soft State 柔性状态，允许系统中的数据处于中间状态</li>
<li>Eventually Consistent 最终一致性，中间状态经过一段时间后会达到最终的数据一致性</li>
</ul>
<h2 id="分布式消息通信"><a href="#分布式消息通信" class="headerlink" title="分布式消息通信"></a>分布式消息通信</h2><p>微服务架构中，一个业务会被拆分成多个微服务，各个服务之间相互通信完成整体功能。系统之间通信协作通常有两种：</p>
<ul>
<li>Http/RPC 通信：优点是通信实时，缺点是服务之间的耦合性高</li>
<li>消息通信：优点降低服务之间耦合性，提高了系统的处理能力，缺点是通信非实时</li>
</ul>
<h3 id="RocketMQ"><a href="#RocketMQ" class="headerlink" title="RocketMQ"></a>RocketMQ</h3><p>低延迟、高可靠、可伸缩、易于使用的分布式消息中间件，高吞吐、低延迟、海量消息堆积，同时提供顺序消息、事务消息、定时消息、消息重试与追踪。</p>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2021/04/18/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BMySQL/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2021/04/18/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BMySQL/" class="post-title-link" itemprop="url">一步一步之MySQL</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-04-18 11:23:31" itemprop="dateCreated datePublished" datetime="2021-04-18T11:23:31+08:00">2021-04-18</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-04-22 08:24:01" itemprop="dateModified" datetime="2021-04-22T08:24:01+08:00">2021-04-22</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/database/" itemprop="url" rel="index">
                    <span itemprop="name">database</span>
                  </a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>614</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><blockquote>
<p>MySQL 是目前使用较为广泛的开源关系型数据库，国内因为阿里的实践推广，MySQL在国内还是有很大的受众群。</p>
</blockquote>
          <!--noindex-->
            <div class="post-button">
              <a class="btn" href="/2021/04/18/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BMySQL/#more" rel="contents">
                阅读全文 &raquo;
              </a>
            </div>
          <!--/noindex-->
        
      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2021/04/04/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BJava%E4%B8%AD%E7%9A%84%E6%B1%A0%E5%8C%96%E6%8A%80%E6%9C%AF/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2021/04/04/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BJava%E4%B8%AD%E7%9A%84%E6%B1%A0%E5%8C%96%E6%8A%80%E6%9C%AF/" class="post-title-link" itemprop="url">一步一步之Java中的池化技术</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-04-04 14:43:51" itemprop="dateCreated datePublished" datetime="2021-04-04T14:43:51+08:00">2021-04-04</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-04-18 11:22:12" itemprop="dateModified" datetime="2021-04-18T11:22:12+08:00">2021-04-18</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/java/" itemprop="url" rel="index">
                    <span itemprop="name">java</span>
                  </a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>1.9k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="池化"><a href="#池化" class="headerlink" title="池化"></a>池化</h2><blockquote>
<p>池化技术是性能调优的重要措施，思想是对象放到池子里，使用的时候从池子拿到对象，用完的时候归还对象，降低资源分配以及释放的开销，从而提升性能。实际项目中，每天都在使用池化技术。</p>
</blockquote>
          <!--noindex-->
            <div class="post-button">
              <a class="btn" href="/2021/04/04/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BJava%E4%B8%AD%E7%9A%84%E6%B1%A0%E5%8C%96%E6%8A%80%E6%9C%AF/#more" rel="contents">
                阅读全文 &raquo;
              </a>
            </div>
          <!--/noindex-->
        
      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

  </div>

  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><span class="page-number current">2</span><a class="page-number" href="/page/3/">3</a><a class="extend next" rel="next" href="/page/3/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let activeClass = CONFIG.comments.activeClass;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Issac Young"
      src="/images/author.jpg">
  <p class="site-author-name" itemprop="name">Issac Young</p>
  <div class="site-description" itemprop="description">现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">26</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">19</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/IssacYoung2013" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;IssacYoung2013" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:issacyoung@msn.cn" title="E-Mail → mailto:issacyoung@msn.cn" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

<div class="copyright">
  
  &copy; 2020 – 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Issac Young</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
      <span class="post-meta-item-text">站点总字数：</span>
    <span title="站点总字数">64k</span>
</div>


        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

</body>
</html>
<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/clicklove.js"></script>

